package cn.myframe.controller.sys;


import cn.myframe.entity.sys.SysLogEntity;
import cn.myframe.entity.sys.SysUserEntity;
import cn.myframe.redis.RedisService;
import cn.myframe.service.cache.CacheService;
import cn.myframe.service.sys.SysLogService;
import cn.myframe.service.sys.SysParameterService;
import cn.myframe.service.sys.SysUserService;
import cn.myframe.shiro.JWTUtil;
import cn.myframe.shiro.ShiroUtils;
import cn.myframe.utils.CryptPwdUtil;
import cn.myframe.utils.DateUtils;
import cn.myframe.utils.IPUtils;
import cn.myframe.utils.constant.STATUS;
import cn.myframe.utils.core.R;
import com.google.code.kaptcha.Producer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;


/**
 * 登录相关
 * 
 * @author  ynz
 * @email   ynz@myframe.cn
 * @version 创建时间：2017年11月21日 下午12:24:01
 */
@Controller
@Slf4j
public class SysLoginController {

	@Autowired
	private SysUserService sysUserService;

	@Autowired
	private Producer producer;

	@Autowired
	private CacheService cacheService;

	@Autowired
	private RedisService redisService;

	@Autowired
	private SysLogService sysLogService;

	@Autowired
	private SysParameterService sysParameterService;

	@Value("${server.timeout:30}")
    private int timeout;

	@RequestMapping("captcha.jpg")
	public void captcha(String t,HttpServletResponse response)throws ServletException, IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
		String text = cacheService.putCaptchaCache(t);

        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        //保存到shiro session
     //   ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
	}
	
	/**
	 * 登录
	 * @throws Exception 
	 */
	@ResponseBody
	@RequestMapping(value = "/sys/login", method = RequestMethod.POST)
	public R login(String  username, String password, String captcha, boolean rememberMe, String language, String unique,
				   HttpServletRequest request)throws Exception {
		String errorTimesStr = sysParameterService.getValue("ErrorLoginTimes");
		String lockHourStr = sysParameterService.getValue("BanLoginTime");
		Integer errorTimes = Integer.valueOf(StringUtils.isEmpty(errorTimesStr) ? "3" : errorTimesStr);
		Integer lockHour = Integer.valueOf(StringUtils.isEmpty(lockHourStr) ? "2" : lockHourStr);
		String kaptcha = cacheService.getCaptchaCache(unique);
		if(captcha.equals(kaptcha)){
			SysUserEntity sysUser = sysUserService.queryByName(username);
			if (sysUser == null) {
				return R.error("用户名或密码错误");
			}
			if (STATUS.STOPUSED.getValue() == sysUser.getStatus()) {
				return R.error("用户已被停用");
			}
			if (STATUS.LOCK.getValue() == sysUser.getStatus()) {
				Date banLoginTime = DateUtils.parseDate(sysUser.getBanLoginTime(), DateUtils.DATE_TIME_PATTERN);
				if (banLoginTime.getTime() > DateUtils.CurrentTime()) {
					return R.error("输入错误密码超过[" + errorTimes + "]次！账号被锁,解锁时间[" + sysUser.getBanLoginTime() + "]！");
				}
				redisService.remove("loginErrorTimes:" + username);
				sysUser.setBanLoginTime("");
				sysUser.setStatus(STATUS.USED.getValue());
				sysUserService.updateById(sysUser);
			}
			String pwd = CryptPwdUtil.hmacSha256(sysUser.getSalt()+ sysUser.getUsername(),password);
			if(sysUser.getPassword().equals(pwd)){
				String token = JWTUtil.sign(username, pwd);
				String freshToken = JWTUtil.sign(username, pwd+token ,TimeUnit.MINUTES.toMillis(timeout));
				redisService.hmSet("JWTToken","JWT-SESSION-"+username,freshToken);
				insertLoginLog(username, request);
				redisService.remove("loginErrorTimes:" + username);
				return R.ok().put("Authorization",token);
			} else {
				if (!"admin".equals(username)) {
					Integer times = redisService.increment("loginErrorTimes:" + username, 1L).intValue();
					if (times >= errorTimes) {
						Date date = DateUtils.addHours(new Date(), lockHour);
						String dataStr = DateUtils.format(date, DateUtils.DATE_TIME_PATTERN);
						sysUser.setBanLoginTime(dataStr);
						sysUser.setStatus(STATUS.LOCK.getValue());
						sysUserService.updateById(sysUser);
						return R.error("输入错误密码超过[" + errorTimes + "]次！账号被锁,解锁时间[" + dataStr + "]！");
					} else {
						return R.error("密码不正确,输入错误密码" + errorTimes + "次，账号将被锁。错误次数[" + times + "]");
					}
				}
				return R.error("用户名或密码错误");
			}
		}
		return R.error("验证码不正确");
	}

	private void insertLoginLog(String username, HttpServletRequest request) {
		SysLogEntity logEntity = new SysLogEntity();
		logEntity.setUsername(username);
		logEntity.setOperation("logLogin");
		logEntity.setMethod("cn.myframe.controller.sys.SysLoginController.login()");
		logEntity.setIp(IPUtils.getIpAddr(request));
		logEntity.setCreateDate(new Date());
		logEntity.setCreateBy(1L);
		logEntity.setType(1);
		logEntity.setClassName("SysLoginController");
		sysLogService.insert(logEntity);
	}

	/**
	 * 退出
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.POST)
	@ResponseBody
	public R logout() {
		ShiroUtils.logout();
		return R.ok();
	}
	
	
}
